﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace Lib.Update
{
    public partial class UpdateForm : Form
    {
        public bool AppCall { get; set; }

        Thread thUpdate = null;

        public UpdateForm()
        {
            InitializeComponent();
        }

        private void Updater_Load(object sender, EventArgs e)
        {
            using (SQLDB db = new SQLDB())
            {
                object obj = db.ExecScalar("Select Agr3 From ZZ_System Where ID=5");
                lblVer.Text = ToString(obj);
            }
        }

        private void SetText(string text)
        {
            if (!this.AppCall)
                this.Invoke(new MethodInvoker(delegate() { txt.Text += text + "\r\n"; }));
        }

        private void SetProgress(int value)
        {
            if (!this.AppCall)
                this.Invoke(new MethodInvoker(delegate() { prog.Value = value; }));
        }

        private string ToString(object value)
        {
            try
            {
                return value.ToString();
            }
            catch
            {
                return "";
            }
        }

        private bool ToBoolean(object value)
        {
            try
            {
                return Convert.ToBoolean(value);
            }
            catch
            {
                return false;
            }
        }

        public void RunUpdate()
        {
            try
            {
                if (!File.Exists(Application.StartupPath + @"\Updates\Fix_Pack.zip")) return;
                EmptyFolder(Application.StartupPath + @"\Updates");

                SetText("Upzip packed.");

                UnZipFile(Application.StartupPath + @"\Updates\Fix_Pack.zip");
                Application.DoEvents();

                SetProgress(2);

                if (!File.Exists(Application.StartupPath + @"\Updates\Info.xml"))
                    return;

                SetText("Read header xml.");

                DataSet ds = new DataSet("ds");
                ds.ReadXml(Application.StartupPath + @"\Updates\Info.xml");
                if (ds == null || ds.Tables.Count <= 0) return;//Finish

                SetProgress(3);

                string currVer = "";
                string toVer = "";

                DataTable Head = ds.Tables["Head"];
                if (Head != null || Head.Rows.Count > 0)
                {
                    currVer = Head.Rows[0]["CurrentVersion"].ToString();
                    toVer = Head.Rows[0]["UpgradeToVersion"].ToString();
                    bool Runtime = ToBoolean(Head.Rows[0]["UpgradeRuntime"]);

                    if (AppCall && !Runtime)
                    {
                        //if (UpdateMessage != null)
                        //{
                        //    //UpdateMessage("Vui lòng đóng phần mềm & mở lại để tiến hành cập nhật.", new EventArgs());
                        //    return;
                        //}
                        return;
                    }
                }

                SetProgress(4);

                SetText("Read data xml.");

                DataTable Data = ds.Tables["Data"];
                if (Data == null || Data.Rows.Count <= 0) return;

                string FS = "", ExcSQL = "", Copy = "", newest = "";
                FS = Data.Rows[0]["FS"].ToString();
                ExcSQL = Data.Rows[0]["ExcSQL"].ToString();
                Copy = Data.Rows[0]["Copy"].ToString();

                SetProgress(5);

                SetText("Beginning update data.");

                using (SQLDB db = new SQLDB())
                {
                    object obj = db.ExecScalar("Select Agr3 From ZZ_System Where ID=5");

                    if (currVer.Trim() == ToString(obj).Trim())
                    {
                        db.BeginTrans();
                        try
                        {
                            SetText("Update function or store.");

                            FileInfo[] arr = (new DirectoryInfo(Application.StartupPath + @"\Updates\" + FS)).GetFiles();
                            if (!object.Equals(arr, null) && arr.Length > 0)
                            {
                                foreach (FileInfo fs in arr)
                                {
                                    StreamReader sr = fs.OpenText();
                                    string sql = sr.ReadToEnd();
                                    db.ExecNonQuery(sql);
                                    sr.Close();
                                }
                            }

                            SetProgress(35);
                            SetText("Update SQL command text.");

                            arr = (new DirectoryInfo(Application.StartupPath + @"\Updates\" + ExcSQL)).GetFiles();
                            if (!object.Equals(arr, null) && arr.Length > 0)
                            {
                                foreach (FileInfo fs in arr)
                                {
                                    StreamReader sr = fs.OpenText();
                                    string sql = sr.ReadToEnd();
                                    db.ExecNonQuery(sql);
                                    sr.Close();
                                }
                            }

                            SetProgress(65);

                            db.ExecNonQuery("Update ZZ_System Set Agr3='" + toVer + "' Where ID=5");

                            db.CommitTrans();
                        }
                        catch (Exception ex)
                        {
                            db.RoolbackTrans();
                        }
                    }

                    newest = ToString(db.ExecScalar("Select Agr3 From ZZ_System Where ID=5"));
                }
                if (toVer == newest)
                {
                    SetText("Copy files.");

                    DirectoryInfo directoryInfo = new DirectoryInfo(Application.StartupPath + @"\Updates\" + Copy);
                    if (directoryInfo.GetFiles().Length > 0)
                    {
                        foreach (FileInfo file in directoryInfo.GetFiles())
                        {
                            file.CopyTo(Application.StartupPath + @"\" + file.Name, true);
                            SetText(file.Name);
                        }
                    }
                    if (directoryInfo.GetDirectories().Length > 0)
                    {
                        foreach (DirectoryInfo sub in directoryInfo.GetDirectories())
                        {
                            CopyAll(sub, new DirectoryInfo(Application.StartupPath + @"\" + sub.Name));
                            //sub.MoveTo(Application.StartupPath);
                            SetText(sub.Name);
                        }
                    }

                    SetProgress(95);
                }

                RemoveFiles();

                SetProgress(100);
                SetText("Upgrade done.");
            }
            catch (Exception ex)
            {
                SetText(ex.Message);
            }
        }

        private void RunApp()
        {
            this.Invoke(new MethodInvoker(delegate()
            {
                Process.Start(Application.StartupPath + @"\NET Cafe.exe");
                this.Close();
            }));
        }

        private void RemoveFiles()
        {
            SetText("Remove upgrade files.");
            File.Delete(Application.StartupPath + @"\Updates\Fix_Pack.zip");
            EmptyFolder(Application.StartupPath + @"\Updates");
        }

        public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
        {
            // Check if the target directory exists, if not, create it.
            if (Directory.Exists(target.FullName) == false)
            {
                Directory.CreateDirectory(target.FullName);
            }

            // Copy each file into it's new directory.
            foreach (FileInfo fi in source.GetFiles())
            {
                Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
                fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
            }

            // Copy each subdirectory using recursion.
            foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
            {
                DirectoryInfo nextTargetSubDir =
                    target.CreateSubdirectory(diSourceSubDir.Name);
                CopyAll(diSourceSubDir, nextTargetSubDir);
            }
        }

        private void EmptyFolder(string Path)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(Path);

            foreach (FileInfo file in directoryInfo.GetFiles())
            {
                if (file.Name.ToLower() == "Fix_Pack.zip".ToLower()) continue;

                file.Delete();
            }

            foreach (DirectoryInfo sub in directoryInfo.GetDirectories())
            {
                sub.Delete(true);
            }
        }

        private void btUp_Click(object sender, EventArgs e)
        {
            if (!AppCall)
            {
                foreach (Process winProcess in Process.GetProcesses())
                {
                    if (winProcess.ProcessName.ToLower() == "NET Cafe".ToLower())
                    {
                        winProcess.Kill();
                    }
                }
            }

            prog.Minimum = 0;
            prog.Maximum = 100;
            prog.Value = 0;

            thUpdate = new Thread(new ThreadStart(RunUpdate));
            thUpdate.IsBackground = true;
            thUpdate.Start();
        }

        private void btClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Escape)
                this.Close();
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private static bool UnZipFile(string InputPathOfZipFile)
        {
            bool ret = true;
            try
            {
                if (File.Exists(InputPathOfZipFile))
                {
                    string baseDirectory = Path.GetDirectoryName(InputPathOfZipFile);

                    using (ZipInputStream ZipStream = new ZipInputStream(File.OpenRead(InputPathOfZipFile)))
                    {
                        ZipEntry theEntry;
                        while ((theEntry = ZipStream.GetNextEntry()) != null)
                        {
                            if (theEntry.IsFile)
                            {
                                if (theEntry.Name != "")
                                {
                                    string strNewFile = @"" + baseDirectory + @"\" + theEntry.Name;
                                    if (File.Exists(strNewFile))
                                    {
                                        continue;
                                    }

                                    using (FileStream streamWriter = File.Create(strNewFile))
                                    {
                                        int size = 2048;
                                        byte[] data = new byte[2048];
                                        while (true)
                                        {
                                            size = ZipStream.Read(data, 0, data.Length);
                                            if (size > 0)
                                                streamWriter.Write(data, 0, size);
                                            else
                                                break;
                                        }
                                        streamWriter.Close();
                                    }
                                }
                            }
                            else if (theEntry.IsDirectory)
                            {
                                string strNewDirectory = @"" + baseDirectory + @"\" + theEntry.Name;
                                if (!Directory.Exists(strNewDirectory))
                                {
                                    Directory.CreateDirectory(strNewDirectory);
                                }
                            }

                            System.Windows.Forms.Application.DoEvents();
                        }
                        ZipStream.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                ret = false;
            }
            return ret;
        } 
    }
}
